package com.blue.user.service.Impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blue.user.mapper.LitUserServiceMapper;
import com.blue.user.service.LitUserService;
import com.litblue.common.utils.RandomUtils;
import com.litblue.common.utils.UserContext;
import com.litblue.common.utils.VerificationCodeGenerator;
import com.litblue.starter.cache.redis.RedisCache;
import com.litblue.starter.cache.redis.RedisKeys;
import com.litblue.starter.core.AjaxResult;
import com.litblue.starter.pojo.user.domian.LitUserInfo;
import com.litblue.starter.pojo.user.dto.LitUserInfoDto;
import lombok.AllArgsConstructor;
import net.sf.jsqlparser.expression.LongValue;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@AllArgsConstructor
public class LitUserServiceImpl extends ServiceImpl<LitUserServiceMapper, LitUserInfo> implements LitUserService{

    private final RedisCache redisCache;

    @PostConstruct
    private void initAuthKey(){
        String publicKey = redisCache.getCacheObject(RedisKeys.PUBLIC_KEY);
        String privateKey = redisCache.getCacheObject(RedisKeys.PRIVATE_KEY);
        if (!StrUtil.isEmpty(publicKey)&&!StrUtil.isEmpty(privateKey)){
            return;
        }
        try {
            HashMap<String, String> map = SaSecureUtil.rsaGenerateKeyPair();
            String pbk = map.get("public").toString();
            String prk = map.get("private").toString();
            redisCache.setCacheObject(RedisKeys.PUBLIC_KEY, pbk);
            redisCache.setCacheObject(RedisKeys.PRIVATE_KEY, prk);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public AjaxResult genPhoneCode(String phone) {
        String code = VerificationCodeGenerator.generateVerificationCode();
        System.out.println("code = " + code);
        redisCache.setCacheObject(phone,code,5, TimeUnit.MINUTES);
        return new AjaxResult<>("验证码已发送","200");
    }

    @Override
    public AjaxResult loginUser(LitUserInfoDto litUserInfoDto) {
        String loginMethod = litUserInfoDto.getLoginMethod();
        if (loginMethod.equals("0")){
            String userName = litUserInfoDto.getUserName();
            String passWord = litUserInfoDto.getPassWord();
            LambdaQueryWrapper<LitUserInfo> queryWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<LitUserInfo> eq = queryWrapper.eq(LitUserInfo::getUserName, userName);
            LitUserInfo userInfo = this.baseMapper.selectOne(eq);
            if (userInfo==null){
                return new AjaxResult<>("用户名不存在","400");
            }
            String prk = redisCache.getCacheObject(RedisKeys.PRIVATE_KEY);
            String decPass = SaSecureUtil.rsaDecryptByPrivate(prk,userInfo.getPass());
            if (!passWord.equals(decPass)){
                return new AjaxResult<>("密码错误","400");
            }
            StpUtil.login(userInfo.getId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            HashMap<Object, Object> map = new HashMap<>();
            map.put("token",tokenInfo);
            map.put("userInfo",userInfo);
            return new AjaxResult<>("登录成功","200",map);
        }
        if (loginMethod.equals("1")){
            String code = litUserInfoDto.getCode();
            String phoneNumber = litUserInfoDto.getPhoneNumber();
            String verificationCode = redisCache.getCacheObject(phoneNumber);
            if (!code.equals(verificationCode)){
                return new AjaxResult<>("验证码错误","400");
            }
            redisCache.deleteObject(phoneNumber);
            LambdaQueryWrapper<LitUserInfo> queryWrapper = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<LitUserInfo> eq = queryWrapper.eq(LitUserInfo::getPhoneNumber, phoneNumber);
            LitUserInfo userInfo = this.baseMapper.selectOne(eq);
            if (userInfo==null){

                LitUserInfo userInfo1 = new LitUserInfo();
                userInfo1.setPhoneNumber(phoneNumber);
                userInfo1.setBackImg("");
                userInfo1.setPersonDes("个人简介");
                userInfo1.setUniversity("清华大学");
                userInfo1.setBirthday("1999-01-01");
                userInfo1.setBlueCode("CODE"+ RandomUtils.generateRandomUsername());
                userInfo1.setNickName("昵称"+ RandomUtils.generateRandomUsername());
                userInfo1.setAvatar("");
                userInfo1.setUserName(RandomUtils.generateRandomUsername());
//                加密密码
                String encPass = getEnc();
                userInfo1.setPass(encPass);
                userInfo1.setCreateTime(new Date());
                userInfo1.setCreateBy(userInfo1.getUserName());
                this.baseMapper.insert(userInfo1);
                StpUtil.login(userInfo1.getId());
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                HashMap<Object, Object> map = new HashMap<>();
                map.put("token",tokenInfo);
                map.put("userInfo",userInfo1);
                return new AjaxResult<>("登录成功","200",map);
            }else {
                StpUtil.login(userInfo.getId());
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                HashMap<Object, Object> map = new HashMap<>();
                map.put("token",tokenInfo);
                map.put("userInfo",userInfo);
                return new AjaxResult<>("登录成功","200",map);
            }


        }
        if (loginMethod.equals("2")){
            return new AjaxResult<>("暂未开放","400");
        }
        return new AjaxResult<>("登录方式错误","400");
    }

    @Override
    public LitUserInfo queryUserInfo(Long id) {
        RedisKeys redisKeys = RedisKeys.forUser(String.valueOf(id));
        LitUserInfo cacheObject = redisCache.getCacheObject(redisKeys.USER_KEY);
        if (cacheObject!=null){
            return cacheObject;
        }
        LitUserInfo userInfo = baseMapper.selectById(id);
        if (userInfo!=null){
            redisCache.setCacheObject(RedisKeys.USER_KEY,userInfo);
            return userInfo;
        }
        return null;
    }

    @Override
    public AjaxResult editUserInfo(LitUserInfo litUserInfo) {
        Long userId = UserContext.getUser();
        litUserInfo.setId(userId);
        baseMapper.updateById(litUserInfo);
        RedisKeys redisKeys = RedisKeys.forUser(String.valueOf(userId));
        redisCache.deleteObject(redisKeys.USER_KEY);
        LitUserInfo userInfo = queryUserInfo(userId);
        return new  AjaxResult("修改成功","200",userInfo);
    }

    private String getEnc() {
        String pbk = redisCache.getCacheObject(RedisKeys.PUBLIC_KEY);
        String encPass = SaSecureUtil.rsaEncryptByPublic(pbk,"123456");
        return encPass;
    }
}
